#pragma once


#include <string>
#include <unistd.h>
#include <stdio.h>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

class my_shell
{
    bool parse_command(const string&command) // 解析用户输入
    {
        stringstream ss(command);
        string token;
        int flag = 0;
        while (ss >> token)
        {
            flag = 1;
            _argv.push_back(token);
        }
        if (flag == 0)
        {
            return false;
        }
        return true;
    }
    bool perform_command() // 执行用户命令
    {
        // 判断是否是内建命令
        if (_argv[0] == "cd")
        {
            if (_argv.size() != 2)
            {
                cout << "-bash: cd: parameter error" << endl;
                return false;
            }
            if (chdir(_argv[1].c_str()) < 0)
            {
                cout << "-bash: cd: path does not exist" << endl;
                return false;
            }
            else
            {
                PWD = _argv[1];
                _cwd = _argv[1];
            }
            return true;
        }
        // 普通命令
        int n = fork();
        if (n == 0)
        {
            char *argv[_argv.size() + 1];
            char *env[_env.size() + 1];

            for (int i = 0; i < _argv.size(); i++)
            {
                argv[i] = (char *)_argv[i].c_str();
            }
            for (int i = 0; i < _env.size(); i++)
            {
                env[i] = (char *)_env[i].c_str();
            }
            argv[_argv.size()] = nullptr;
            env[_env.size()] = nullptr;
            execvpe(_argv[0].c_str(), argv, env);
        }
        waitpid(n, nullptr, 0);

        _argv.clear();
        return true;
    }
public:
    my_shell()
    {
        // 读取环境变量表初始化
        USER = getenv("USER");
        PWD = getenv("PWD");
        char buf[1024] = {0};
        getcwd(buf, 1024);
        _cwd = buf;

        _env.push_back(USER);
        _env.push_back(PWD);
    }
    
    void command(const string&com)
    {
        parse_command(com);
        perform_command();
    }
private:
    string USER;          // 用户名
    string PWD;           // 环境变量PWD
    string _cwd;          // 当前工作路径
    vector<string> _env;  // 环境变量表
    vector<string> _argv; // 命令行参数表
};
